﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections;
using System.DirectoryServices;
using Novell.Directory.Ldap;
using System.Security.Cryptography;
using WebCurriculumn.Helper;

/// <summary>
/// LdapAuthentication の概要の説明です
/// </summary>
public class LdapAuthentication
{
    private string _path;
    private string _filterAttribute;
	public LdapAuthentication()
	{
		//
		// TODO: コンストラクタ ロジックをここに追加します
		//
	}
    public LdapAuthentication(string path)
    {
        _path = path;
    }
    public bool IsAuthenticated(string username, string pwd)
    {
        try
        {
            int ldapVersion = LdapConnection.Ldap_V3;
            int ldapPort = LdapConnection.DEFAULT_PORT;
            String ldapHost="";
            String loginDN="";
            String password="";
            String targetDN = "";
            String objectDN="";
            String testPassword="";
            byte[] userPassword;
            byte[] mdByte;
            MD5CryptoServiceProvider md5;
            ldapHost = IniFile.readIni("LDAPHost");
            ldapPort = int.Parse(IniFile.readIni("LDAPPort"));
            ldapVersion = int.Parse(IniFile.readIni("LDAPVersion"));
            loginDN = IniFile.readIni("LDAPRootDN");
            password = IniFile.readIni("LDAPRootPwd");
            targetDN = IniFile.readIni("LDAPTargetDN");
            LdapConnection conn = new LdapConnection();
            conn.Connect(ldapHost, ldapPort);
            if (!conn.Connected)
            {            
                return false;
            }
            
            //conn.Bind(ldapVersion, loginDN, password);
            conn.Bind(loginDN, password);
            objectDN = "cn=" + username + "," + targetDN;
            testPassword = pwd;

            md5 = new MD5CryptoServiceProvider();
            userPassword = Encoding.ASCII.GetBytes(testPassword);
            mdByte = md5.ComputeHash(userPassword);

            //String mdString = System.BitConverter.ToString(mdByte);
            String mdPwd = "{MD5}" + Convert.ToBase64String(mdByte);

            LdapAttribute attr = new LdapAttribute("userPassword", mdPwd);
            bool correct = conn.Compare(objectDN, attr);
            conn.Disconnect();
            return correct;

        }
        catch (Exception ex)
        {
            //throw new Exception("Error authenticating user. " + ex.Message);
            return false;
        }
        return true;
    }

    public bool IsAuthenticated(string domain, string username, string pwd)
    {
        string domainAndUsername = domain + @"\" + username;        
        DirectoryEntry entry = new DirectoryEntry(_path,
                                                   domainAndUsername, pwd);
        
        
        try
        {
            // Bind to the native AdsObject to force authentication. 
            Object obj = entry.NativeObject;
            DirectorySearcher search = new DirectorySearcher(entry);
            search.Filter = "(SAMAccountName=" + username + ")";
            search.PropertiesToLoad.Add("cn");
            SearchResult result = search.FindOne();
            if (null == result)
            {
                return false;
            }
            // Update the new path to the user in the directory
            _path = result.Path;
            _filterAttribute = (String)result.Properties["cn"][0];
        }
        catch (Exception ex)
        {
            throw new Exception("Error authenticating user. " + ex.Message);
        }
        return true;
    }

    public string GetGroups()
    {
        DirectorySearcher search = new DirectorySearcher(_path);
        search.Filter = "(cn=" + _filterAttribute + ")";
        search.PropertiesToLoad.Add("memberOf");
        StringBuilder groupNames = new StringBuilder();
        try
        {
            SearchResult result = search.FindOne();
            int propertyCount = result.Properties["memberOf"].Count;
            String dn;
            int equalsIndex, commaIndex;

            for (int propertyCounter = 0; propertyCounter < propertyCount;
                 propertyCounter++)
            {
                dn = (String)result.Properties["memberOf"][propertyCounter];

                equalsIndex = dn.IndexOf("=", 1);
                commaIndex = dn.IndexOf(",", 1);
                if (-1 == equalsIndex)
                {
                    return null;
                }
                groupNames.Append(dn.Substring((equalsIndex + 1),
                                  (commaIndex - equalsIndex) - 1));
                groupNames.Append("|");
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error obtaining group names. " + ex.Message);
        }
        return groupNames.ToString();
    }


}
